package tp.badugi.server;

import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import static tp.badugi.server.Action.*;

public class GameLogicControllerTest {

	Table table;
	GamePlayController controller;
	List<Player> players;
	Player player0;
	Player player1;
	Player player2;
	Player player3;
	Player player4;
	Player player5;
	List<Card> cards;
	
	@Before
	public void before() {
		table = mock(Table.class);
		controller = new GamePlayController(table);
		cards = new ArrayList<Card>();
		cards.add(Card.ACE_CLUBS);
		cards.add(Card.TWO_DIAMONDS);
		cards.add(Card.THREE_SPADES);
		cards.add(Card.FOUR_HEARTS);
		players = new ArrayList<Player>();
		player0 = mock(Player.class);
		when(player0.getCards()).thenReturn(cards);
		player1 = mock(Player.class);
		when(player1.getCards()).thenReturn(cards);
		player2 = mock(Player.class);
		when(player2.getCards()).thenReturn(cards);
		player3 = mock(Player.class);
		when(player3.getCards()).thenReturn(cards);
		player4 = mock(Player.class);
		when(player4.getCards()).thenReturn(cards);
		player5 = mock(Player.class);
		
	}
	
	@Test
	public void testOverseeGamePlayScenario01() throws Exception {
		// Prepare
		final int PLAYER_WITH_BUTTON = 3;
		when(table.getPotSize()).thenReturn(10000L);
		when(player1.getChipCount()).thenReturn(1000L);
		players.add(player0);
		players.add(player1);
		players.add(player2);
		players.add(player3);
		
		// Round 1			Round 2			Round 3			Round 4
		when(player0.requestAction(anyBoolean(), anyInt())) 				// <- Small blind
		.thenReturn(CALL).thenReturn(FOLD);
		when(player1.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CHECK).thenReturn(FOLD);
		when(player2.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CALL).thenReturn(BET).thenReturn(CHECK).thenReturn(ALL_IN);
		when(player3.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CALL).thenReturn(CALL).thenReturn(CHECK).thenReturn(CALL);
		
		//Showdown
		when(player0.isInPlay()).thenReturn(false);
		when(player1.isInPlay()).thenReturn(false);
		when(player2.isInPlay()).thenReturn(true);
		when(player3.isInPlay()).thenReturn(true);
		
		// Act out
		controller.overseeDeal(players, PLAYER_WITH_BUTTON);
		
		// Verify
		verify(player0, times(2)).requestAction(anyBoolean(), anyInt());
		verify(player1, times(2)).requestAction(anyBoolean(), anyInt());
		verify(player2, times(4)).requestAction(anyBoolean(), anyInt());
		verify(player3, times(4)).requestAction(anyBoolean(), anyInt());
	}
	
	@Test
	public void testOverseeGamePlayScenario01DifferentButton() throws Exception {
		// Prepare
		final int PLAYER_WITH_BUTTON = 1;
		when(table.getPotSize()).thenReturn(10000L);
		when(player3.getChipCount()).thenReturn(1000L);
		players.add(player0);
		players.add(player1);
		players.add(player2);
		players.add(player3);
		
		// Round 1			Round 2			Round 3			Round 4
		when(player0.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CALL).thenReturn(BET).thenReturn(CHECK).thenReturn(ALL_IN);
		when(player1.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CALL).thenReturn(CALL).thenReturn(CHECK).thenReturn(CALL);
		when(player2.requestAction(anyBoolean(), anyInt())) 				// <- Small blind
		.thenReturn(CALL).thenReturn(FOLD);
		when(player3.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CHECK).thenReturn(FOLD);
		
		//Showdown
		when(player0.isInPlay()).thenReturn(true);
		when(player1.isInPlay()).thenReturn(true);
		when(player2.isInPlay()).thenReturn(false);
		when(player3.isInPlay()).thenReturn(false);
		
		// Act out
		controller.overseeDeal(players, PLAYER_WITH_BUTTON);
		
		// Verify
		verify(player0, times(4)).requestAction(anyBoolean(), anyInt());
		verify(player1, times(4)).requestAction(anyBoolean(), anyInt());
		verify(player2, times(2)).requestAction(anyBoolean(), anyInt());
		verify(player3, times(2)).requestAction(anyBoolean(), anyInt());
	}
	
	@Test
	public void testOverseeGamePlaySinglePlayerLeft() throws Exception {
		// Prepare
		final int PLAYER_WITH_BUTTON = 2;
		when(table.getPotSize()).thenReturn(10000L);
		when(player0.getName()).thenReturn("JUnitPlayer1");
		when(player1.getChipCount()).thenReturn(1000L);
		players.add(player0);
		players.add(player1);
		players.add(player2);
		
		// Round 1			Round 2			Round 3			Round 4
		when(player0.requestAction(anyBoolean(), anyInt())) 			// <- Small blind
		.thenReturn(CALL).thenReturn(BET);
		when(player1.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CHECK).thenReturn(FOLD);
		when(player2.requestAction(anyBoolean(), anyInt()))
		.thenReturn(CALL).thenReturn(FOLD);
		
		//Showdown
		when(player0.isInPlay()).thenReturn(true);
		when(player1.isInPlay()).thenReturn(false);
		when(player2.isInPlay()).thenReturn(false);
		
		// Act out
		controller.overseeDeal(players, PLAYER_WITH_BUTTON);
		
		// Verify
		verify(player0, times(2)).requestAction(anyBoolean(), anyInt());
		verify(player1, times(2)).requestAction(anyBoolean(), anyInt());
		verify(player2, times(2)).requestAction(anyBoolean(), anyInt());
	}


}
